<?php
/**
 * 	Bushido
 *
 * @category   Bushido
 * @package    Bushido_FusionCharts
 * @copyright  Copyright (c) 2008-2009 Nathan Keyes
 * @author Nathan Keyes
 * @version    $Id: FusionCharts.php 7 2009-11-14 22:42:08Z nkeyes $
 */

/**
 * 
 * @author Nathan Keyes
 *
 */
 class Bushido_FusionCharts extends Bushido_Object
 {
	//free chart types
	CONST FREE_AREA = 'FCF_Area2D';
	CONST FREE_COLUMN = 'FCF_Column2D';
	CONST FREE_COLUMN_3D = 'FCF_Column3D';
	CONST FREE_LINE = 'FCF_Line';
	CONST FREE_MULTI_SERIES_COLUMN_3D = 'FCF_MSColumn3D';
	CONST FREE_MULTI_SERIES_COLUMN_3D_LINE_DUAL_Y_AXIS = 'FCF_MSColumn3DLineDY';
	CONST FREE_PIE_3D = 'FCF_Pie3D';
	CONST FREE_STACKED_COLUMN_3D = 'FCF_StackedColumn3D';
	
	
	//premium chart types
 	CONST ANGULAR_GAGUE = 'AngularGauge';
	CONST AREA = 'Area2D';
	CONST BAR = 'Bar2D';
	CONST BUBBLE = 'Bubble';
	CONST BULB = 'Bulb';
	CONST CANDLESTICK = 'CandleStick';
	CONST COLUMN = 'Column2D';
	CONST COLUMN_3D = 'Column3D';
	CONST CYLINDAR = 'Cylinder';
	CONST DOUGHNUT = 'Doughnut2D';
	CONST DOUGHNUT_3D = 'Doughnut3D';
	CONST AREA_DRAGGABLE = 'DragArea';
	CONST COLUMN_DRAGGABLE = 'DragColumn2D';
	CONST LINE_DRAGGABLE = 'DragLine';
	CONST NODE_DRAGGABLE = 'DragNode';
	CONST DRAWING_PAD = 'DrawingPad';
	CONST ERROR_BAR = 'ErrorBar2D';
	CONST FUNNEL = 'Funnel';
	CONST GANTT = 'Gantt';
	CONST BULLET_HORIZONTAL = 'HBullet';
	CONST LED_HORIZONTAL = 'HLED';
	CONST LINEAR_GAGUE_HORIZONTAL = 'HLinearGauge';
	CONST MULTI_SERIES_AREA_INVERSE = 'InverseMSArea';
	CONST MULTI_SERIES_COLUMN_INVERSE = 'InverseMSColumn2D';
	CONST MULTI_SERIES_LINE_INVERSE = 'InverseMSLine';
	CONST KAGI = 'Kagi';
	CONST LINE = 'Line';
	CONST MULTI_SERIES_COLUMN_LOG = 'LogMSColumn2D';
	CONST MULTI_SERIES_LINE_LOG = 'LogMSLine';
	CONST MULTI_SERIES_AREA = 'MSArea';
	CONST MULTI_SERIES_BAR = 'MSBar2D';
	CONST MULTI_SERIES_BAR_3D = 'MSBar3D';
	CONST MULTI_SERIES_COLUMN = 'MSColumn2D';
	CONST MULTI_SERIES_COLUMN_3D = 'MSColumn3D';
	CONST MULTI_SERIES_COLUMN_3D_LINE_DUAL_Y_AXIS = 'MSColumn3DLineDY';
	CONST MULTI_SERIES_COLUMN_3D_LINE = 'MSColumnLine3D';
	CONST MULTI_SERIES_COMBINED = 'MSCombi2D';
	CONST MULTI_SERIES_COMBINED_DUAL_Y_AXIS = 'MSCombiDY2D';
	CONST MULTI_SERIES_LINE = 'MSLine';
	CONST MULTI_SERIES_SPLINE = 'MSSpline';
	CONST MULTI_SERIES_SPLINE_AREA = 'MSSplineArea';
	CONST MULTI_SERIES_STACKED_COLUMN = 'MSStackedColumn2D';
	CONST MULTI_SERIES_STACKED_COLUMN_LINE_DUAL_Y_AXIS = 'MSStackedColumn2DLineDY';
	CONST LINE_MULTI_AXIS = 'MultiAxisLine';
	CONST PIE_MULTI_LEVEL = 'MultiLevelPie';
	CONST PIE = 'Pie2D';
	CONST PIE_3D = 'Pie3D';
	CONST PYRAMID = 'Pyramid';
	CONST RADAR = 'Radar';
	CONST AREA_REAL_TIME = 'RealTimeArea';
	CONST COLUMN_REAL_TIME = 'RealTimeColumn';
	CONST LINE_REAL_TIME = 'RealTimeLine';
	CONST LINE_REAL_TIME_DUAL_Y_AXIS = 'RealTimeLineDY';
	CONST STACKED_AREA_REAL_TIME = 'RealTimeStackedArea';
	CONST STACKED_COLUMN_REAL_TIME = 'RealTimeStackedColumn';
	CONST SINGLE_SERIES_GRID = 'SSGrid';
	CONST SCATTER = 'Scatter';
	CONST AREA_SCROLL = 'ScrollArea2D';
	CONST COLUMN_SCROLL = 'ScrollColumn2D';
	CONST COMBINED_SCROLL = 'ScrollCombi2D';
	CONST COMBINED_SCROLL_DUAL_Y_AXIS = 'ScrollCombiDY2D';
	CONST LINE_SCROLL = 'ScrollLine2D';
	CONST STACKED_COLUMN_SCROLL = 'ScrollStackedColumn2D';
	CONST SCATTER_SELECT = 'SelectScatter';
	CONST COLUMN_SPARK = 'SparkColumn';
	CONST LINE_SPARK = 'SparkLine';
	CONST WIN_LOSS_SPARK = 'SparkWinLoss';
	CONST SPLINE = 'Spline';
	CONST SPLINE_AREA = 'SplineArea';
	CONST STACKED_AREA = 'StackedArea2D';
	CONST STACKED_BAR = 'StackedBar2D';
	CONST STACKED_BAR_3D = 'StackedBar3D';
	CONST STACKED_COLUMN = 'StackedColumn2D';
	CONST STACKED_COLUMN_3D = 'StackedColumn3D';
	CONST STACKED_COLUMN_3D_LINE_DUAL_Y_AXIS = 'StackedColumn3DLineDY';
	CONST THERMOMOMETER = 'Thermometer';
	CONST BULLET_VERTICAL = 'VBullet';
	CONST LED_VERTICAL = 'VLED';
	CONST WATERFALL = 'Waterfall2D';
	
	
	/**
	 * 
	 * @return void
	 */
	public function __construct(){}
	
	/**
	 * 
	 * @return void
	 */
	public function __clone(){}
	
	
	/**
	 * 
	 * @param $chart
	 * @param $configOptions
	 * @param $theme
	 * @return string
	 */
	public static function getChart($chart, $configOptions = array(), $theme = null)
	{
		if ($chart instanceof Bushido_Datagram_Abstract)
		{
			$chartXML = urlencode(self::getChartXML($chart, $configOptions, $theme));
		}
		else
		{
			$chartXML = urlencode($chart);
		}
		
		$debug = isset($configOptions['debug']) ? $configOptions['debug'] : 0;
		
		if(!$theme || !($theme instanceof Bushido_FusionCharts_Theme_Abstract))
		{
			$themeName = isset($configOptions['theme']) ? $configOptions['theme'] : 'Default';
			$theme = Bushido_FusionCharts_Theme::factory($themeName);
		}
		
		$chartType = $theme->getChartType();
		
		$chartId = isset($configOptions['id']) ? $configOptions['id'] : 'chart_' . round(microtime() *10000, 0) ;
		$chartIdDiv = $chartId . '_FusionChartDiv';
		//$chartName = $chart->getChartName();
		//$chartShortName = str_replace('Bushido_Model_Datagram_', '', $chartName);
		//$chartURLOptions = $chart->getConfig()->getConfigOptions($customFormat = true, null, null, '/', '/');
		//$chartCaption = $chart->getConfig()->getConfigOption('caption');
		$chartWidth = isset($configOptions['chartWidth']) ? $configOptions['chartWidth'] : 1000;
		$chartHeight = isset($configOptions['chartHeight']) ? $configOptions['chartHeight'] : 500;
		
		$baseUrl = Zend_Controller_Front::getInstance()->getBaseUrl();
				
		$render_chart = <<<RENDERCHART
	<span id="$chartIdDiv" align="center" >
		$chartId
	</span>
	<script>	
		//Instantiate the Chart
			var chart_$chartId = new FusionCharts('$baseUrl/includes/swf/FusionCharts/$chartType.swf', "$chartId", "$chartWidth", "$chartHeight", "$debug", "1");
			chart_$chartId.addParam('wmode', 'transparent');
			chart_$chartId.setDataXML('$chartXML');
			chart_$chartId.render("$chartIdDiv");
			//chart_$chartId = null;
	</script>
RENDERCHART;

  	return $render_chart;

	}
	
	
	/**
	 * 
	 * @param $datagram
	 * @param $configOptions
	 * @param $theme
	 * @return string
	 */
	public static function getChartDOMElement(Bushido_Datagram_Abstract $datagram, $configOptions = array(), $theme = null)
	{
		if(!$theme || !($theme instanceof Bushido_FusionCharts_Theme_Abstract))
		{
			$themeName = isset($configOptions['theme']) ? $configOptions['theme'] : 'Default';
			$theme = Bushido_FusionCharts_Theme::factory($themeName);
		}
		
		$dataSeriesList = $datagram->getRawData();
		$chartNode = $theme->getXML();
		$caption = isset($configOptions['caption']) ? $configOptions['caption'] : ' ';
		$chartNode->addAttribute('caption', $caption);
		if($theme->isMultiSeries())
		{
			$categoriesNode = simplexml_load_string("<categories />");
		}
		
		if(is_array($dataSeriesList))
		{
			
			foreach($dataSeriesList as $dataSeries)
			{
				if($theme->isMultiSeries())
				{
					$datasetNode = simplexml_load_string($theme->getDataSetNode($dataSeries['name']));
				}
				
				foreach($dataSeries['data'] as $dataSeriesData)
				{
					$setNode = simplexml_load_string($theme->getDataNode($dataSeriesData['label'], $dataSeriesData['value']));
					if($theme->isMultiSeries())
					{
						$existingCategoryNodes = $categoriesNode->xpath('//category[@label="' . html_entity_decode($theme->getCategoryLabel($dataSeriesData['label'])) . '"]');
						if(!$existingCategoryNodes)
						{
							$categoryNode = simplexml_load_string($theme->getCategoryNode($dataSeriesData['label']));
							Bushido_Utils::simplexml_append($categoriesNode, $categoryNode);
						}
						Bushido_Utils::simplexml_append($datasetNode, $setNode);
					}
					else
					{
						Bushido_Utils::simplexml_append($chartNode, $setNode);
					}
					
				}
				if($theme->isMultiSeries())
				{
					Bushido_Utils::simplexml_append($chartNode, $datasetNode);
				}
			}
		}
		if($theme->isMultiSeries())
		{
			Bushido_Utils::simplexml_append($chartNode, $categoriesNode);
		}
		return str_replace(array('<?xml version="1.0"?>', "\n"), array('', ''), $chartNode->asXML());
	}
	
	/**
	 * 
	 * @param $chart
	 * @param $configOptions
	 * @param $theme
	 * @return string
	 */
	public static function getChartXML(Bushido_Datagram_Abstract $chart, $configOptions = array(), $theme = null)
	{
		if(!$theme || !($theme instanceof Bushido_FusionCharts_Theme_Abstract))
		{
			$themeName = isset($configOptions['theme']) ? $configOptions['theme'] : 'Default';
			$theme = Bushido_FusionCharts_Theme::factory($themeName);
		}
		$dataSeriesList = $chart->getRawData();
		$chartNode = $theme->getXML();
		$caption = isset($configOptions['caption']) ? $configOptions['caption'] : ' ';
		$chartNode->addAttribute('caption', $caption);
		if($theme->isMultiSeries())
		{
			$categoriesNode = simplexml_load_string("<categories />");
		}
		
		if(is_array($dataSeriesList))
		{
			
			foreach($dataSeriesList as $dataSeries)
			{
				if($theme->isMultiSeries())
				{
					$datasetNode = simplexml_load_string($theme->getDataSetNode($dataSeries['name']));
				}
				
				foreach($dataSeries['data'] as $dataSeriesData)
				{
					$setNode = simplexml_load_string($theme->getDataNode($dataSeriesData['label'], $dataSeriesData['value']));
					if($theme->isMultiSeries())
					{
						$existingCategoryNodes = $categoriesNode->xpath('//category[@label="' . html_entity_decode($theme->getCategoryLabel($dataSeriesData['label'])) . '"]');
						if(!$existingCategoryNodes)
						{
							$categoryNode = simplexml_load_string($theme->getCategoryNode($dataSeriesData['label']));
							Bushido_Utils::simplexml_append($categoriesNode, $categoryNode);
						}
						Bushido_Utils::simplexml_append($datasetNode, $setNode);
					}
					else
					{
						Bushido_Utils::simplexml_append($chartNode, $setNode);
					}
					
				}
				if($theme->isMultiSeries())
				{
					Bushido_Utils::simplexml_append($chartNode, $datasetNode);
				}
			}
		}
		if($theme->isMultiSeries())
		{
			Bushido_Utils::simplexml_append($chartNode, $categoriesNode);
		}
		return str_replace(array('<?xml version="1.0"?>', "\n"), array('', ''), $chartNode->asXML());
	}
 }
